#include "stdafx.h"
#include "XmlTag.h"
#include "../../../ThirdParty/tinyxml-2.5.3/tinyxml.h"
#include "../../../Components/Common/LibCommon/util.h"

struct _StatusPair
{
	CServerStatus::eStatus status;
	char text[32];
};

_StatusPair g_ServerStatusText[] = 
{
	//Main Status
	{CServerStatus::Main_Off, "Off"},
	{CServerStatus::Main_Connecting, "Connecting"},
	{CServerStatus::Main_Ready, "Ready"},
	// Login Status
	{CServerStatus::Account_Offline, "Offline"},
	{CServerStatus::Account_Logging, "Logging"},
	{CServerStatus::Account_Online, "Online"},
	// PublicIP Status and 	NAT Traversal Status
	{CServerStatus::Avail, "Available"},
	{CServerStatus::Detecting, "Detecting"},
	{CServerStatus::Unavail, "Unavailable"},
	// Announce status
	{CServerStatus::Announce_OK, "OK"},
	{CServerStatus::Announce_Going, "Announcing"},
	{CServerStatus::Announce_Fail, "Fail"},
	{CServerStatus::Null_Status, ""}
};

const char * GetServerStatusText(CServerStatus::eStatus status)
{
	for (int i = 0; g_ServerStatusText[i].status != CServerStatus::Null_Status; i++)
	{
		if (g_ServerStatusText[i].status == status)
			return g_ServerStatusText[i].text;
	}
	return NULL;
}

CServerStatus::eStatus GetServerStatusFromText(const char * status)
{
	for (int i = 0; g_ServerStatusText[i].text != NULL; i++)
	{
		if (strcmp(g_ServerStatusText[i].text, status) == 0)
			return g_ServerStatusText[i].status;
	}
	return CServerStatus::Null_Status;
}

bool ShareFolderListXML::Load(const char * pBuf)
{	
	TiXmlDocument * XmlDoc = new TiXmlDocument();
	const char * xml = XmlDoc->Parse(pBuf);
	TiXmlElement * Root = XmlDoc->FirstChildElement("ShareFolderList");
	if (Root == NULL)
		return false;
	TiXmlElement * ShareFolder = Root->FirstChildElement("ShareFolder");
	while (ShareFolder)
	{
		const char * name = ShareFolder->Attribute("name");
		const char * path = ShareFolder->Attribute("path");
		if (name && path)
		{
			ShareFolderItem item;
			item.name = UTF8ToWideChar(string(name));
			item.path = UTF8ToWideChar(string(path));
			List.push_back(item);
		}
		ShareFolder = ShareFolder->NextSiblingElement("ShareFolder");
	}
	return true;
}

const char * ShareFolderListXML::Save()
{
	TiXmlDocument xmldoc;
	TiXmlDeclaration * dec = new TiXmlDeclaration("1.0", "utf-8", "yes");
	TiXmlElement * ShareFolderList = new TiXmlElement("ShareFolderList");
	for (unsigned int i = 0; i < List.size(); i++)
	{
		TiXmlElement * ShareFolder = new TiXmlElement("ShareFolder");
		ShareFolder->SetAttribute("name", WideCharToUTF8(List[i].name).c_str());
		ShareFolder->SetAttribute("path", WideCharToUTF8(List[i].path).c_str());
		ShareFolderList->LinkEndChild(ShareFolder);
	}
	xmldoc.LinkEndChild(dec);
	xmldoc.LinkEndChild(ShareFolderList);

	TiXmlPrinter Printer;
	xmldoc.Accept(&Printer);
	m_LatestSaved = Printer.CStr();
	return m_LatestSaved.c_str();
}

bool ShareFolderXML::Load(const char * pBuf)
{	
	TiXmlDocument * XmlDoc = new TiXmlDocument();
	const char * xml = XmlDoc->Parse(pBuf);	
	TiXmlElement * Root = XmlDoc->FirstChildElement("ShareFolder");
	if (!Root)
		return false;
	string ShareFolder = Root->Attribute("path");
	if (ShareFolder[ShareFolder.size()-1] != L'\\')
		ShareFolder += "\\";
	TiXmlElement * ShareItem = Root->FirstChildElement("Item");
	while (ShareItem)
	{
		const char * name = ShareItem->Attribute("name");
		const char * type = ShareItem->Attribute("type");
		const char * filetype = ShareItem->Attribute("filetype");
		if (name && type)
		{
			ShareFolderXML::ShareItem item;
			item.name = UTF8ToWideChar(string(name));
			item.type = type;
			string path = ShareFolder + name;
			item.path = UTF8ToWideChar(string(path));
			if (filetype)
			{
				item.filetype = filetype;
			}
			ShareItems.push_back(item);
		}
		ShareItem = ShareItem->NextSiblingElement("Item");
	}
	return true;
}

const char * ShareFolderXML::Save()
{	
	TiXmlDocument xmldoc;
	TiXmlDeclaration * dec = new TiXmlDeclaration("1.0", "utf-8", "yes");	
	TiXmlElement * ShareFolder = new TiXmlElement("ShareFolder");
	ShareFolder->SetAttribute("path", WideCharToUTF8(ShareFolderPath).c_str());
	for (unsigned int i = 0; i < ShareItems.size(); i++)
	{
		TiXmlElement *Item = new TiXmlElement("Item");
		Item->SetAttribute("name", WideCharToUTF8(ShareItems[i].name).c_str());
		Item->SetAttribute("type", ShareItems[i].type.c_str());
		if (ShareItems[i].type != "folder")
		{
			Item->SetAttribute("filetype", ShareItems[i].filetype.c_str());
		}
		ShareFolder->LinkEndChild(Item);
	}
	xmldoc.LinkEndChild(dec);
	xmldoc.LinkEndChild(ShareFolder);

	TiXmlPrinter Printer;
	xmldoc.Accept(&Printer);
	m_LatestSaved = Printer.CStr();
	return m_LatestSaved.c_str();
}

bool ServerStatusXML::Load(const char * pBuf)
{
	TiXmlDocument * XmlDoc = new TiXmlDocument();
	const char * xml = XmlDoc->Parse(pBuf);	
	TiXmlElement * Root = XmlDoc->FirstChildElement("ServerStatus");
	if (!Root)
		return false;
	TiXmlElement * Main = Root->FirstChildElement("Main");
	const char * Status = Main->Attribute("Status");
	if (Status)
	{
		m_ServerStatus.m_MainStatus = GetServerStatusFromText(Status);
	}
	TiXmlElement * Login = Root->FirstChildElement("Login");
	Status = Login->Attribute("Status");
	if (Status)
	{
		m_ServerStatus.m_LoginStatus = GetServerStatusFromText(Status);
	}
	TiXmlElement * PublicIP = Root->FirstChildElement("PublicIP");
	Status = PublicIP->Attribute("Status");
	if (Status)
	{
		m_ServerStatus.m_IPStatus = GetServerStatusFromText(Status);
		const char * pubip = PublicIP->Attribute("IP");
		if (pubip)
			m_ServerStatus.m_PublicIP = pubip;
	}
	TiXmlElement * NAT = Root->FirstChildElement("NAT");
	Status = NAT->Attribute("Traversal");
	if (Status)
	{
		m_ServerStatus.m_NATTStatus = GetServerStatusFromText(Status);
	}
	const char * NATexist = NAT->Attribute("Exist");
	if (NATexist)
		m_ServerStatus.m_HasNAT = (strcmp(NATexist, "True") == 0);
	TiXmlElement * AnnounceIP = Root->FirstChildElement("AnnounceIP");
	Status = AnnounceIP->Attribute("Status");
	if (Status)
	{
		m_ServerStatus.m_AnnounceStatus = GetServerStatusFromText(Status);
		const char * annip = AnnounceIP->Attribute("IP");
		if (annip)
			m_ServerStatus.m_PublicIP = annip;
	}
	return true;
}

const char * ServerStatusXML::Save()
{
	TiXmlDocument xmldoc;
	TiXmlDeclaration * dec = new TiXmlDeclaration("1.0", "utf-8", "yes");
	TiXmlElement *ServerStatus = new TiXmlElement("ServerStatus");

	TiXmlElement *Main = new TiXmlElement("Main");
	Main->SetAttribute("Status", GetServerStatusText(m_ServerStatus.m_MainStatus));
	
	TiXmlElement *Login = new TiXmlElement("Login");
	Login->SetAttribute("Status", GetServerStatusText(m_ServerStatus.m_LoginStatus));

	TiXmlElement * PublicIP = new TiXmlElement("PublicIP");
	PublicIP->SetAttribute("Status", GetServerStatusText(m_ServerStatus.m_IPStatus));
	PublicIP->SetAttribute("IP", m_ServerStatus.m_PublicIP.c_str());

	TiXmlElement * NAT = new TiXmlElement("NAT");
	NAT->SetAttribute("Exist", m_ServerStatus.m_HasNAT?"True":"False");
	NAT->SetAttribute("Traversal", GetServerStatusText(m_ServerStatus.m_NATTStatus));

	TiXmlElement * AnnounceIP = new TiXmlElement("AnnounceIP");
	AnnounceIP->SetAttribute("Status", GetServerStatusText(m_ServerStatus.m_AnnounceStatus));
	AnnounceIP->SetAttribute("IP", m_ServerStatus.m_AnnounceIP.c_str());

	xmldoc.LinkEndChild(dec);
	xmldoc.LinkEndChild(ServerStatus);
	ServerStatus->LinkEndChild(Main);
	ServerStatus->LinkEndChild(Login);
	ServerStatus->LinkEndChild(PublicIP);
	ServerStatus->LinkEndChild(NAT);
	ServerStatus->LinkEndChild(AnnounceIP);

	TiXmlPrinter Printer;
	xmldoc.Accept(&Printer);
	m_LatestSaved = Printer.CStr();
	return m_LatestSaved.c_str();
}

bool LoginResponseXML::Load(const char * pBuf)
{
	TiXmlDocument * XmlDoc = new TiXmlDocument();
	const char * xml = XmlDoc->Parse(pBuf);	
	TiXmlElement * Root = XmlDoc->FirstChildElement("LoginResponse");
	if (!Root)
		return false;
	const char * Result = Root->Attribute("Status");
	m_bLogin = (strcmp(Result, "OK") == 0);
	return true;
}

const char * LoginResponseXML::Save()
{
	TiXmlDocument xmlres;
	TiXmlDeclaration * dec = new TiXmlDeclaration("1.0", "utf-8", "yes");
	TiXmlElement * LoginRes = new TiXmlElement("LoginResponse");
	if (m_bLogin)
		LoginRes->SetAttribute("Status", "OK");
	else
		LoginRes->SetAttribute("Status", "ERROR");
	xmlres.LinkEndChild(dec);
	xmlres.LinkEndChild(LoginRes);
	TiXmlPrinter Printer;
	xmlres.Accept(&Printer);
	m_LatestSaved = Printer.CStr();
	return m_LatestSaved.c_str();
}

bool LogoutResponseXML::Load(const char * pBuf)
{
	TiXmlDocument * XmlDoc = new TiXmlDocument();
	const char * xml = XmlDoc->Parse(pBuf);	
	TiXmlElement * Root = XmlDoc->FirstChildElement("LogoutResponse");
	if (!Root)
		return false;
	const char * Result = Root->Attribute("Status");
	m_bLogout = (strcmp(Result, "OK") == 0);
	return true;
}

const char * LogoutResponseXML::Save()
{
	TiXmlDocument xmlres;
	TiXmlDeclaration * dec = new TiXmlDeclaration("1.0", "utf-8", "yes");
	TiXmlElement * LoginRes = new TiXmlElement("LogoutResponse");
	if (m_bLogout)
		LoginRes->SetAttribute("Status", "OK");
	else
		LoginRes->SetAttribute("Status", "ERROR");
	xmlres.LinkEndChild(dec);
	xmlres.LinkEndChild(LoginRes);
	TiXmlPrinter Printer;
	xmlres.Accept(&Printer);
	m_LatestSaved = Printer.CStr();
	return m_LatestSaved.c_str();
}

bool AddFolderResponseXML::Load(const char * pBuf)
{
	return false;
}

const char * AddFolderResponseXML::Save()
{
	return false;
}

bool RemoveFolderResponseXML::Load(const char * pBuf)
{
	return false;
}

const char * RemoveFolderResponseXML::Save()
{
	return false;
}

